package dataStructure.linearList.impl;

import dataStructure.collection.exception.IndexException;
import dataStructure.linearList.LinearList;
import dataStructure.linearList.node.LinkedNode;

import java.util.Objects;

/**
 * @author guihuo (E-mail:1620657419@qq.com)
 * @version v1.0 创建时间：2017/10/28 13:38
 *          单链表
 *          <p>
 *          链表还有双向链表，单循环链表，多重链表
 */
public class LinkedList<T> implements LinearList<T> {

    /**
     * '
     * 头节点
     */
    private LinkedNode<T> head = new LinkedNode<T>(null, null);

    /**
     * 当前数组最大长度
     */
    private int length = 0;

    @Override
    public int getLength() {
        return length;
    }

    @Override
    public T get(int index) {
        if (index < 0 || index >= length) {
            throw new IndexException();
        }
        LinkedNode<T> result = head.next();
        while (index > 0) {
            result = result.next();
            index--;
        }
        return result.getValue();
    }

    @Override
    public int findIndex(T t) {
        if (Objects.isNull(t)) {
            return -1;
        }
        LinkedNode<T> result = head.next();
        int index = 0;
        while (result != null) {
            if (result.getValue().equals(t)) {
                return index;
            }
            result = result.next();
            index++;
        }
        return -1;
    }

    @Override
    public void insert(T t) {
        insert(t, length);
    }

    @Override
    public void insert(T t, int index) {
        if (index < 0 || index > length) {
            throw new IndexException();
        }
        LinkedNode<T> previousNode = head;
        while (index > 0) {
            previousNode = previousNode.next();
            index--;
        }
        previousNode.setNextNode(new LinkedNode<T>(t, previousNode.next()));
        length++;
    }

    @Override
    public void delete(int index) {
        LinkedNode<T> previousNode = head;
        for (int i = 0; i < index; i++) {
            previousNode = previousNode.next();
        }
        previousNode.setNextNode(previousNode.next().next());
        length--;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder("LinkedList{nodeList=[");
        LinkedNode<T> next = head.next();
        for (int i = 1; next != null; i++) {
            if (i == length) {
                str.append(next);
            } else {
                str.append(next).append(", ");
            }
            next = next.next();
        }
        str.append("], length=").append(length).append("}");
        return str.toString();
    }
}